﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using SIO = System.IO;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.ComponentModel;

namespace remes.BLoc
{
   /// <summary>
   /// Delegate for handling StdOutput strings
   /// </summary>
   /// <param name="line">One line of output</param>
   public delegate void StdOutLineDelegate(string line);

   /// <summary>
   /// Class for managing BLoc project settings and running all BLoc core tasks
   /// </summary>
   public class BLocProject : INotifyPropertyChanged
   {
      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="path">Full path to C# project file</param>
      /// <param name="setDefaultIfMissing">true if missing settings should be set to default values</param>
      public BLocProject(string path, bool setDefaultIfMissing)
      {
         Configurations = new Collection<BuildConfiguration>();

         LoadFromProject(path, setDefaultIfMissing);
      }

      private readonly XNamespace _xNS = "http://schemas.microsoft.com/developer/msbuild/2003";
      //private readonly XNamespace _xBLocNS = "BLoc";

      private void OpenProjectFile(out XDocument xPrj, out XElement xDefPropertyGroup, IList<BuildConfiguration> configurations)
      {
         if (configurations != null)
         {
            configurations.Clear();
         }
         xPrj = XDocument.Load(ProjectPath);

         var xPropertyGroups = xPrj.Root.Elements(_xNS + "PropertyGroup");
         xDefPropertyGroup = null;
         foreach (var xPropGoup in xPropertyGroups)
         {
            var xConditionAttr = xPropGoup.Attribute("Condition");
            if (xConditionAttr == null && xPropGoup.Element(_xNS + "ProductVersion") != null)
            {
               xDefPropertyGroup = xPropGoup;
            }
            else if (configurations != null && xConditionAttr != null)
            {
               string c = null;
               int n2 = xConditionAttr.Value.LastIndexOf('\'');
               if (n2 >= 0)
               {
                  int n1 = xConditionAttr.Value.LastIndexOf('\'', n2 - 1);
                  if (n1 >= 0)
                  {
                     c = xConditionAttr.Value.Substring(n1 + 1, n2 - n1 - 1);
                  }
               }
               if (c != null)
               {
                  Configurations.Add(new BuildConfiguration(c, ((string)xPropGoup.Element(_xNS + "OutputPath")) ?? String.Empty));
               }
            }
         }
         if (xDefPropertyGroup == null)
         {
            throw new Exception("Project file does not contain a default PropertyGroup!");
         }
         if (configurations != null && configurations.Count == 0)
         {
            throw new Exception("Project file does not contain Configurations!");
         }
      }

      private void LoadFromProject(string path, bool setDefaultIfMissing)
      {
         XDocument xPrj;
         XElement xDefPropertyGroup;
         ProjectPath = SIO.Path.GetFullPath(path);

         OpenProjectFile(out xPrj, out xDefPropertyGroup, Configurations);

         AssemblyName = (string)xDefPropertyGroup.Element(_xNS + "AssemblyName");
         if (String.IsNullOrWhiteSpace(AssemblyName))
         {
            throw new Exception("Project file does not contain the Property 'AssemblyName'!");
         }

         TargetFrameworkVersion = (string)xDefPropertyGroup.Element(_xNS + "TargetFrameworkVersion");
         if (String.IsNullOrWhiteSpace(TargetFrameworkVersion))
         {
            throw new Exception("Project file does not contain the Property 'TargetFrameworkVersion'!");
         }

         var outputType = (string)xDefPropertyGroup.Element(_xNS + "OutputType");
         if (String.IsNullOrWhiteSpace(outputType))
         {
            throw new Exception("Project file does not contain the Property 'OutputType'!");
         }
         if (outputType.IndexOf("exe", StringComparison.OrdinalIgnoreCase) >= 0)
         {
            AssemblyExtension = ".exe";
         }
         else
         {
            AssemblyExtension = ".dll";
         }

         try
         {
            var xLDTLF = xDefPropertyGroup.Element(_xNS + "LocalizationDirectivesToLocFile");
            if(xLDTLF == null)
            {
               LocalizationDirectivesToLocFile = remes.BLoc.LocalizationDirectivesToLocFile.None;
            }
            else
            {
               LocalizationDirectivesToLocFile = (LocalizationDirectivesToLocFile)Enum.Parse(typeof(LocalizationDirectivesToLocFile), xLDTLF.Value);
            }
         }
         catch (Exception ex)
         {
            throw new Exception("Project file property 'LocalizationDirectivesToLocFile' contains an invalid value", ex);
         }

         var uiCulture = (string)xDefPropertyGroup.Element(_xNS + "UICulture");
         if (!String.IsNullOrEmpty(uiCulture))
         {
            OriginalLang = uiCulture;
            OriginalLangInSatelite = true;
         }
         else
         {
            var originalCulture = (string)xDefPropertyGroup.Element(_xNS + "BLoc_OriginalCulture");
            if (!String.IsNullOrEmpty(originalCulture))
            {
               OriginalLang = originalCulture;
               OriginalLangInSatelite = false;
            }
            else if (setDefaultIfMissing)
            {
               OriginalLang = "en-us";
               OriginalLangInSatelite = true;
            }
            else
            {
               throw new Exception("Project file does not contain the Property 'UICulture' or 'BLoc_OriginalCulture'!");
            }
         }

         var translationFilePath = (string)xDefPropertyGroup.Element(_xNS + "BLoc_TranslationFilePath");
         if (!String.IsNullOrEmpty(translationFilePath))
         {
            TranslationFilePath = translationFilePath;
         }
         else if (setDefaultIfMissing)
         {
            TranslationFilePath = String.Format("{0}.bloct", AssemblyName);
         }
         else
         {
            throw new Exception("Project file does not contain the Property 'BLoc_TranslationFilePath'!");
         }

         var preBuildActions = (string)xDefPropertyGroup.Element(_xNS + "BLoc_PreBuildActions");
         if (String.IsNullOrEmpty(preBuildActions))
         {
            PreBuildActions = 0;
         }
         else
         {
            PreBuildActions = (PreBuildActions)Enum.Parse(typeof(PreBuildActions), preBuildActions);
         }

         var postBuildActions = (string)xDefPropertyGroup.Element(_xNS + "BLoc_PostBuildActions");
         if (String.IsNullOrEmpty(postBuildActions))
         {
            PostBuildActions = 0;
         }
         else
         {
            PostBuildActions = (PostBuildActions)Enum.Parse(typeof(PostBuildActions), postBuildActions);
         }
      }

      public void UpdateProjectFile()
      {
         XDocument xPrj;
         XElement xDefPropertyGroup;
         OpenProjectFile(out xPrj, out xDefPropertyGroup, null);

         // remove old entries for original culture
         var xUICulture = xDefPropertyGroup.Element(_xNS + "UICulture");
         if (xUICulture != null)
         {
            xUICulture.Remove();
         }
         var xOrigCulture = xDefPropertyGroup.Element(_xNS + "BLoc_OriginalCulture");
         if (xOrigCulture != null)
         {
            xOrigCulture.Remove();
         }

         // add new entry for original culture
         if (OriginalLangInSatelite)
         {
            xDefPropertyGroup.Add(new XElement(_xNS + "UICulture", OriginalLang));
         }
         else
         {
            xDefPropertyGroup.Add(new XElement(_xNS + "BLoc_OriginalCulture", OriginalLang));
         }

         // remove old entry for translation file
         var xTranslationFilePath = xDefPropertyGroup.Element(_xNS + "BLoc_TranslationFilePath");
         if (xTranslationFilePath != null)
         {
            xTranslationFilePath.Remove();
         }
         // add new entry for translation file path
         xDefPropertyGroup.Add(new XElement(_xNS + "BLoc_TranslationFilePath", TranslationFilePath));

         // remove old entry for LocalizationDirectivesToLocFile
         var xLDTLF = xDefPropertyGroup.Element(_xNS + "LocalizationDirectivesToLocFile");
         if (xLDTLF != null)
         {
            xLDTLF.Remove();
         }
         // add new entry for LocalizationDirectivesToLocFile file path
         xDefPropertyGroup.Add(new XElement(_xNS + "LocalizationDirectivesToLocFile", LocalizationDirectivesToLocFile.ToString()));

         var xPreBuildActions = xDefPropertyGroup.Element(_xNS + "BLoc_PreBuildActions");
         if (xPreBuildActions != null)
         {
            xPreBuildActions.Remove();
         }
         if (PreBuildActions != 0)
         {
            xDefPropertyGroup.Add(new XElement(_xNS + "BLoc_PreBuildActions", PreBuildActions.ToString()));
         }

         var xPostBuildActions = xDefPropertyGroup.Element(_xNS + "BLoc_PostBuildActions");
         if (xPostBuildActions != null)
         {
            xPostBuildActions.Remove();
         }
         if (PostBuildActions != 0)
         {
            xDefPropertyGroup.Add(new XElement(_xNS + "BLoc_PostBuildActions", PostBuildActions.ToString()));
         }

         var xPreBuildEvents = xPrj.Root.Descendants(_xNS + "PreBuildEvent").FirstOrDefault();
         if (xPreBuildEvents == null)
         {
            xPreBuildEvents = new XElement(_xNS + "PreBuildEvent");
            xPrj.Root.Add(new XElement(_xNS + "PropertyGroup", xPreBuildEvents));
         }
         var preBuildEvent = String.Format("\"{0}\" \"$(ProjectPath)\" /prebuildactions /configuration:$(ConfigurationName) /platform:$(PlatformName) /nologo /verbose",
            BLocSettings.Instance.BLocCLUPath);
         if (xPreBuildEvents.Value.IndexOf(preBuildEvent, StringComparison.OrdinalIgnoreCase) < 0)
         {
            var lines = xPreBuildEvents.Value.Split('\n');
            for (int n = 0; n < lines.Length; ++n)
            {
               if (lines[n].IndexOf(SIO.Path.GetFileName(BLocSettings.Instance.BLocCLUPath), StringComparison.OrdinalIgnoreCase) > 0
                  && lines[n].IndexOf("/prebuildactions", StringComparison.OrdinalIgnoreCase) > 0)
               {
                  // remove some different pre-build event
                  xPreBuildEvents.Value = String.Empty;
                  for (int nn = 0; nn < lines.Length; ++nn)
                  {
                     if (n != nn)
                     {
                        xPreBuildEvents.Value += lines[nn];
                        if (nn < lines.Length - 1)
                        {
                           xPreBuildEvents.Value += "\n";
                        }
                     }
                  }
                  break;
               }
            }
            if (!String.IsNullOrWhiteSpace(xPreBuildEvents.Value))
            {
               xPreBuildEvents.Value += "\n";
            }
            xPreBuildEvents.Value += preBuildEvent;
         }

         var xPostBuildEvents = xPrj.Root.Descendants(_xNS + "PostBuildEvent").FirstOrDefault();
         if (xPostBuildEvents == null)
         {
            xPostBuildEvents = new XElement(_xNS + "PostBuildEvent");
            xPrj.Root.Add(new XElement(_xNS + "PropertyGroup", xPostBuildEvents));
         }
         var postBuildEvent = String.Format("\"{0}\" \"$(ProjectPath)\" /postbuildactions /configuration:$(ConfigurationName) /platform:$(PlatformName) /nologo /verbose",
            BLocSettings.Instance.BLocCLUPath);
         if (xPostBuildEvents.Value.IndexOf(postBuildEvent, StringComparison.OrdinalIgnoreCase) < 0)
         {
            var lines = xPostBuildEvents.Value.Split('\n');
            for (int n = 0; n < lines.Length; ++n)
            {
               if (lines[n].IndexOf(SIO.Path.GetFileName(BLocSettings.Instance.BLocCLUPath), StringComparison.OrdinalIgnoreCase) > 0
                  && lines[n].IndexOf("/postbuildactions", StringComparison.OrdinalIgnoreCase) > 0)
               {
                  // remove some different post-build event
                  xPostBuildEvents.Value = String.Empty;
                  for (int nn = 0; nn < lines.Length; ++nn)
                  {
                     if (n != nn)
                     {
                        xPostBuildEvents.Value += lines[nn];
                        if (nn < lines.Length - 1)
                        {
                           xPostBuildEvents.Value += "\n";
                        }
                     }
                  }
                  break;
               }
            }
            if (!String.IsNullOrWhiteSpace(xPostBuildEvents.Value))
            {
               xPostBuildEvents.Value += "\n";
            }
            xPostBuildEvents.Value += postBuildEvent;
         }

         SIO.File.Copy(ProjectPath, ProjectPath + ".bak", true);
         xPrj.Save(ProjectPath);

         // update assembly info file
         var assemblyInfoPath = SIO.Path.GetDirectoryName(ProjectPath);
         var appDesignerFolder = (string)xDefPropertyGroup.Element(_xNS + "AppDesignerFolder");
         if (!String.IsNullOrWhiteSpace(appDesignerFolder))
         {
            assemblyInfoPath = SIO.Path.Combine(assemblyInfoPath, appDesignerFolder);
         }
         assemblyInfoPath = SIO.Path.Combine(assemblyInfoPath, "AssemblyInfo.cs");
         if (!SIO.File.Exists(assemblyInfoPath))
         {
            SIO.Path.Combine(SIO.Path.GetDirectoryName(ProjectPath), "AssemblyInfo.cs");
         }

         if (SIO.File.Exists(assemblyInfoPath))
         {
            var output = new List<string>();
            Encoding encoding;
            using (var reader = new SIO.StreamReader(assemblyInfoPath))
            {
               string line;
               encoding = reader.CurrentEncoding;
               bool attributeFound = false;
               while ((line = reader.ReadLine()) != null)
               {
                  if (line.Contains("assembly") && line.Contains("NeutralResourcesLanguage"))
                  {
                     if (OriginalLangInSatelite)
                     {
                        output.Add(String.Format("[assembly: NeutralResourcesLanguage(\"{0}\", UltimateResourceFallbackLocation.Satellite)]", OriginalLang));
                     }
                     else
                     {
                        output.Add(String.Format("[assembly: NeutralResourcesLanguage(\"{0}\", UltimateResourceFallbackLocation.MainAssembly)]", OriginalLang));
                     }
                     attributeFound = true;
                  }
                  else
                  {
                     output.Add(line);
                  }
               }

               if (!attributeFound)
               {
                  if (OriginalLangInSatelite)
                  {
                     output.Add(String.Format("[assembly: NeutralResourcesLanguage(\"{0}\", UltimateResourceFallbackLocation.Satellite)]", OriginalLang));
                  }
                  else
                  {
                     output.Add(String.Format("[assembly: NeutralResourcesLanguage(\"{0}\", UltimateResourceFallbackLocation.MainAssembly)]", OriginalLang));
                  }
               }
            }

            SIO.File.Copy(assemblyInfoPath, assemblyInfoPath + ".bak", true);
            using (var writer = new SIO.StreamWriter(assemblyInfoPath, false, encoding))
            {
               foreach (var line in output)
               {
                  writer.WriteLine(line);
               }
            }
         }
      }

      public string ProjectPath { get; private set; }

      public string AssemblyName { get; private set; }

      public string AssemblyExtension { get; private set; }

      public string TargetFrameworkVersion { get; private set; }

      public IList<BuildConfiguration> Configurations { get; private set; }

      private LocalizationDirectivesToLocFile _LocalizationDirectivesToLocFile;

      public LocalizationDirectivesToLocFile LocalizationDirectivesToLocFile
      {
         get { return _LocalizationDirectivesToLocFile; }
         set
         {
            _LocalizationDirectivesToLocFile = value;
            NotifyPropertyChnaged("LocalizationDirectivesToLocFile");
         }
      }

      private string _OriginalLang;

      public string OriginalLang
      {
         get { return _OriginalLang; }
         set
         {
            _OriginalLang = value;
            NotifyPropertyChnaged("OriginalLang");
         }
      }

      private bool _OriginalLangInSatelite;

      public bool OriginalLangInSatelite
      {
         get { return _OriginalLangInSatelite; }
         set
         {
            _OriginalLangInSatelite = value;
            NotifyPropertyChnaged("OriginalLangInSatelite");
         }
      }

      private string _TranslationFilePath;

      public string TranslationFilePath
      {
         get { return _TranslationFilePath; }
         set
         {
            _TranslationFilePath = value;
            NotifyPropertyChnaged("TranslationFilePath");
         }
      }

      private PreBuildActions _PreBuildActions;

      public PreBuildActions PreBuildActions
      {
         get { return _PreBuildActions; }
         set
         {
            _PreBuildActions = value;
            NotifyPropertyChnaged("PreBuildActions");
         }
      }

      private PostBuildActions _PostBuildActions;

      public PostBuildActions PostBuildActions
      {
         get { return _PostBuildActions; }
         set
         {
            _PostBuildActions = value;
            NotifyPropertyChnaged("PostBuildActions");
         }
      }

      public int DoPreBuildActions(BuildConfiguration configuration, StdOutLineDelegate stdOutCallback = null)
      {
         int returnCode = 0;
         if ((PreBuildActions & BLoc.PreBuildActions.CheckUID) != 0)
         {
            if (stdOutCallback != null)
            {
               stdOutCallback("Checking UID's");
            }
            returnCode = CheckUIDs(stdOutCallback);
         }
         if (returnCode == 0 && (PreBuildActions & BLoc.PreBuildActions.UpdateUID) != 0)
         {
            if (stdOutCallback != null)
            {
               stdOutCallback("Updating UID's");
            }
            returnCode = UpdateUIDs(stdOutCallback);
         }
         return returnCode;
      }

      public int DoPostBuildActions(BuildConfiguration configuration, StdOutLineDelegate stdOutCallback = null)
      {
         int returnCode = 0;
         if ((PostBuildActions & BLoc.PostBuildActions.ParseAssembly) != 0)
         {
            if (stdOutCallback != null)
            {
               stdOutCallback("Parsing assembly");
            }
            returnCode = ParseBaml(configuration, stdOutCallback);
         }
         if (returnCode == 0 && (PostBuildActions & BLoc.PostBuildActions.GenerateAssemblies) != 0)
         {
            if (stdOutCallback != null)
            {
               stdOutCallback("Generating satelite assemblies");
            }
            returnCode = GenerateSateliteAssemblies(configuration, null, stdOutCallback);
         }
         return returnCode;
      }

      public int CheckUIDs(StdOutLineDelegate stdOutCallback = null)
      {
         return ExecuteMSBuild(String.Format("/t:checkuid \"{0}\"", ProjectPath), stdOutCallback);
      }

      public int UpdateUIDs(StdOutLineDelegate stdOutCallback = null)
      {
         return ExecuteMSBuild(String.Format("/t:updateuid \"{0}\"", ProjectPath), stdOutCallback);
      }

      public int ParseBaml(BuildConfiguration configuration, StdOutLineDelegate stdOutCallback = null)
      {
         int returnCode = 0;
         string assemblyPath;
         if (OriginalLangInSatelite)
         {
            // copy the satelite assembly into the output folder
            assemblyPath = SIO.Path.Combine(GetFullOutputPath(configuration), String.Format("{0}.resources.dll", AssemblyName));
            SIO.File.Copy(SIO.Path.Combine(SIO.Path.Combine(GetFullOutputPath(configuration), OriginalLang), String.Format("{0}.resources.dll", AssemblyName)), assemblyPath, true);
         }
         else
         {
            assemblyPath = SIO.Path.Combine(GetFullOutputPath(configuration), String.Format("{0}{1}", AssemblyName, AssemblyExtension));
         }
         try
         {
            var blocOutputFilePath = SIO.Path.Combine(GetFullOutputPath(configuration), "BLoc_tmp.xml");
            var translationFileFullPath = GetTranslationFileFullPath();

            var args = String.Format("/parse \"{0}\" /out: \"{1}\" /verbose /nologo", assemblyPath, blocOutputFilePath);

            if (LocalizationDirectivesToLocFile != remes.BLoc.LocalizationDirectivesToLocFile.None)
            {
               var commentFilePath = SIO.Path.Combine(GetFullOutputPath(configuration), String.Format("{0}.loc", AssemblyName));
               if (SIO.File.Exists(commentFilePath))
               {
                  args += String.Format(" /commentfile: \"{0}\"", commentFilePath);
               }
            }

            returnCode = ExecuteLocBaml(configuration, args, stdOutCallback);
            if(returnCode == 0)
            {
               TranslationSet transFile = new TranslationSet();
               if (SIO.File.Exists(translationFileFullPath))
               {
                  transFile.Load(translationFileFullPath);
               }

               transFile.MergeLocBamlFile(blocOutputFilePath, OriginalLang);

               transFile.SaveAs(translationFileFullPath);
            }
            if (SIO.File.Exists(blocOutputFilePath))
            {
               SIO.File.Delete(blocOutputFilePath);
            }
         }
         catch
         {
            returnCode = 100;
         }
         finally
         {
            if (OriginalLangInSatelite)
            {
               SIO.File.Delete(assemblyPath);
            }
         }
         return returnCode;
      }

      public int GenerateSateliteAssemblies(BuildConfiguration configuration, IEnumerable<string> languages, StdOutLineDelegate stdOutCallback = null)
      {
         string assemblyPath;
         if (OriginalLangInSatelite)
         {
            // copy the satelite assembly into the output folder
            assemblyPath = SIO.Path.Combine(GetFullOutputPath(configuration), String.Format("{0}.resources.dll", AssemblyName));
            SIO.File.Copy(SIO.Path.Combine(SIO.Path.Combine(GetFullOutputPath(configuration), OriginalLang), String.Format("{0}.resources.dll", AssemblyName)), assemblyPath, true);
         }
         else
         {
            assemblyPath = SIO.Path.Combine(GetFullOutputPath(configuration), String.Format("{0}{1}", AssemblyName, AssemblyExtension));
         }
         try
         {
            var args = String.Format("/generate \"{0}\" /trans: \"{1}\" /out: \"{2}\"",
               assemblyPath, GetTranslationFileFullPath(), GetFullOutputPath(configuration));

            if (languages == null)
            {
               args += " /cul:$all";
            }
            else
            {
               foreach (var lang in languages)
               {
                  args += " /cul:" + lang;
               }
            }

            args += " /verbose /nologo";
            return ExecuteLocBaml(configuration, args, stdOutCallback);
         }
         finally
         {
            if (OriginalLangInSatelite)
            {
               SIO.File.Delete(assemblyPath);
            }
         }
      }

      private int ExecuteMSBuild(string arguments, StdOutLineDelegate stdOutCallback)
      {
         return ExecuteToOutput(BLocSettings.Instance.GetMSBuildPath(TargetFrameworkVersion), arguments, stdOutCallback);
      }

      private int ExecuteLocBaml(BuildConfiguration configuration, string arguments, StdOutLineDelegate stdOutCallback)
      {
         var locBamlOutputPath = SIO.Path.Combine(GetFullOutputPath(configuration), SIO.Path.GetFileName(BLocSettings.Instance.LocBamlPath));
         SIO.File.Copy(BLocSettings.Instance.LocBamlPath, locBamlOutputPath, true);
         try
         {
            return ExecuteToOutput(locBamlOutputPath, arguments, stdOutCallback);
         }
         finally
         {
            SIO.File.Delete(locBamlOutputPath);
         }
      }

      private StdOutLineDelegate _StdOutCallback = null;

      private int ExecuteToOutput(string fileName, string arguments, StdOutLineDelegate stdOutCallback)
      {
         var p = new Process();
         p.StartInfo.FileName = fileName;
         p.StartInfo.Arguments = arguments;
         p.StartInfo.UseShellExecute = false;

         _StdOutCallback = stdOutCallback;
         try
         {
            if (stdOutCallback != null)
            {
               p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
               p.StartInfo.RedirectStandardOutput = true;
               p.OutputDataReceived += Process_OutputDataReceived;
            }

            p.Start();

            if (stdOutCallback != null)
            {
               p.BeginOutputReadLine();
            }

            if (!p.HasExited)
            {
               p.WaitForExit();
            }
            return p.ExitCode;
         }
         finally
         {
            _StdOutCallback = null;
         }
      }

      private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
      {
         if (_StdOutCallback != null && !String.IsNullOrEmpty(e.Data))
         {
            _StdOutCallback(e.Data);
         }
      }

      public string GetFullOutputPath(BuildConfiguration configuration)
      {
         var path = SIO.Path.GetFullPath(SIO.Path.Combine(SIO.Path.GetDirectoryName(ProjectPath), configuration.OutputPath));
         if (path.EndsWith("\\"))
         {
            path = path.Substring(0, path.Length - 1);
         }
         return path;
      }

      public string GetTranslationFileFullPath()
      {
         return SIO.Path.GetFullPath(SIO.Path.Combine(SIO.Path.GetDirectoryName(ProjectPath), TranslationFilePath));
      }

      public TranslationSet LoadTranslationSet()
      {
         var set = new TranslationSet();
         set.Load(GetTranslationFileFullPath());
         return set;
      }

      #region INotifyPropertyChanged Members

      protected void NotifyPropertyChnaged(string propertyName)
      {
         var temp = PropertyChanged;
         if (temp != null)
         {
            temp(this, new PropertyChangedEventArgs(propertyName));
         }
      }

      public event PropertyChangedEventHandler PropertyChanged;

      #endregion
   }

   public class BuildConfiguration
   {
      public BuildConfiguration(string condition, string outputPath)
      {
         Condition = condition;
         OutputPath = outputPath;
      }

      public string Condition { get; private set; }
      public string OutputPath { get; private set; }

      public override string ToString()
      {
         return Condition;
      }
   }

   public enum LocalizationDirectivesToLocFile
   {
      None,
      CommentsOnly,
      All
   }

   [Flags]
   public enum PreBuildActions
   {
      CheckUID = 0x01,
      UpdateUID = 0x02
   }

   [Flags]
   public enum PostBuildActions
   {
      ParseAssembly = 0x01,
      GenerateAssemblies = 0x02
   }
}
